const { createApp } = Vue;

const post = async (url, body) => {
    return (await fetch(url, {
        method: 'POST',
        headers: { "Content-Type": "application/json" },
        body: body !== undefined ? JSON.stringify(body) : undefined,
    })).json();
}

const APIs = {
    native: new class Native {
        async version() {
            return post("./version")
        }
        async latest() {
            return post('./latest')
        }
        async translate(word) {
            return post('./translate', { Word: word })
        }
    },
    dummy: new class Dummy {
        async version() {
            return "DUMMY";
        }
        async latest() {
            return { Latest: "DUMMY", ReleaseURL: "" };
        }
        async translate(word) {
            return {
                Word: word,
                Translated: word.toUpperCase(),
                Comment: [],
                Debug: [],
                Err: "",
            };
        }
    },
    web: new class Web {
        async version() {
            return __version();
        }
        async latest() {
            return __latest();
        }
        async translate(word) {
            return __translate(word);
        }
    },
};

const guess_platform = async () => {
    if (["127.0.0.1", "localhost"].includes(window.location.hostname)) {
        const ws = new WebSocket(`ws://${window.location.host}/feeddog`);
        setInterval(() => ws.send("OK"), 1000);

        return "native";
    } if (window.location.origin === "file://" && window.Go === undefined) {
        return "dummy";
    } else {
        const go = new Go();
        const result = await WebAssembly.instantiateStreaming(fetch(XiaowuWebWasm), go.importObject);
        go.run(result.instance);

        return "web";
    }
};


window.addEventListener('load', async () => {
    const platform = await guess_platform();
    console.log("platform:", platform);
    const API = APIs[platform];

    const cached = new Map();

    const app = createApp({
        data() {
            return {
                version: "",
                contentScrollTop: 0,
                input: "",
                output: "",
                tips: [],
                updatable: false,
                release_url: "",
            };
        },
        methods: {
            async onInputChange() {
                if (cached.size > 10000) {
                    cached.clear();
                }

                const lines = this.input.split("\n");
                const mapped = [];
                for (let idx = 0; idx < lines.length; idx += 1) {
                    const line = lines[idx];
                    if (cached.get(line) === undefined) {
                        cached.set(line, await API.translate(line));
                    }
                    mapped.push(cached.get(line));
                }

                this.output = mapped.map(x => x.Translated).join("\n");
                const tips = [];
                mapped.forEach(m => {
                    if (m.Err !== "") {
                        tips.push(m.Word + ": " + m.Err);
                    }
                    const comment = m.Comment || [];
                    if (comment.length > 0) {
                        tips.push(...comment.map(c => m.Word + ": " + c));
                    }
                });
                this.tips = tips;
            },
        },
        async mounted() {
            this.version = await API.version();
            const latest = await API.latest();
            this.updatable = this.version !== latest.Latest;
            this.release_url = latest.ReleaseURL;
        },
    });

    app.use(ElementPlus);
    app.mount('#app');
});